package cn.com.cfae.iras.doc.analyze.parse.tokenizer;

import cn.com.cfae.iras.doc.analyze.parse.RegexUtil;
import cn.com.cfae.iras.doc.analyze.parse.extractor.TableExtractor;
import cn.com.cfae.iras.doc.analyze.parse.kv.TextLayout;
import cn.com.cfae.iras.doc.analyze.parse.model.ExtractBizModel;
import cn.com.cfae.iras.doc.analyze.parse.model.ExtractItem;
import cn.com.cfae.iras.doc.analyze.parse.model.PageModel;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.hankcs.hanlp.dictionary.CustomDictionary;
import com.hankcs.hanlp.tokenizer.NLPTokenizer;
import org.apache.commons.lang.StringUtils;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BaseTokenizer extends TableExtractor {

    public BaseTokenizer() {

    }

    private RegexUtil regexUtil = new RegexUtil();

    protected String CWBB_NB_FORMAT = RegexUtil.CWBB_NB_FORMAT;
    protected String CWBB_JB_FORMAT = RegexUtil.CWBB_JB_FORMAT;
    protected String CWBB_JSNJYQ_FORMAT = RegexUtil.CWBB_JSNJYQ_FORMAT;
    protected String CWBB_KJKM_AMT_FORMAT = RegexUtil.CWBB_KJKM_AMT_FORMAT;
    protected String HYZB_MT_MTCL_FORMAT = RegexUtil.HYZB_MT_MTCL_FORMAT;
    protected String HYZB_MT_XSJG_FORMAT = RegexUtil.HYZB_MT_XSJG_FORMAT;

    protected boolean isYearFormat(String text) {
        Pattern pattern = Pattern.compile(CWBB_NB_FORMAT);
        Matcher matcher = pattern.matcher(text);
        if (matcher.matches()) {
            return true;
        }
        pattern = Pattern.compile(CWBB_JB_FORMAT);
        matcher = pattern.matcher(text);
        if (matcher.matches()) {
            return true;
        }

        pattern = Pattern.compile(CWBB_JSNJYQ_FORMAT);
        matcher = pattern.matcher(text);
        if (matcher.matches()) {
            return true;
        }
        return false;
    }

    protected boolean isAmt(String text) {
        Pattern pattern = Pattern.compile(CWBB_KJKM_AMT_FORMAT);
        Matcher matcher = pattern.matcher(text);

        if (matcher.matches()) {
            return true;
        }
        return false;
    }

    protected boolean isMT_MTCL_UNIT(String text) {
        Pattern pattern = Pattern.compile(HYZB_MT_MTCL_FORMAT);
        Matcher matcher = pattern.matcher(text);
        if (matcher.matches()) {
            return true;
        }
        return false;
    }

    protected boolean isMT_SYKCCL_UNIT(String text) {
        return regexUtil.isMT_SYKCCL(text);
    }

    protected boolean isMT_SCCB_UNIT(String text) {
        return isMT_XSJG_UNIT(text);
    }

    protected boolean isMT_XSJG_UNIT(String text) {
        Pattern pattern = Pattern.compile(HYZB_MT_XSJG_FORMAT);
        Matcher matcher = pattern.matcher(text);
        if (matcher.matches()) {
            return true;
        }
        return false;
    }


    protected RegexUtil getRegexUtil() {
        return regexUtil;
    }

    public void loadCoreSynonyms(ExtractBizModel extractBizModel) {
        List<String> synonyms = extractBizModel.getSynonyms();
        for (String synonym : synonyms) {
            if (CustomDictionary.get(synonym) == null) {
                CustomDictionary.add(synonym);
            }
        }
        for (String coreSynonym : getCoreSynonyms()) {
            CustomDictionary.add(coreSynonym);
        }
        NLPTokenizer.ANALYZER.enableNumberQuantifierRecognize(true).enableCustomDictionaryForcing(true);
    }

    public void loadCoreSynonyms(List<String> synonyms) {
        for (String synonym : synonyms) {
            if (CustomDictionary.get(synonym) == null) {
                CustomDictionary.add(synonym);
            }
        }
        for (String coreSynonym : getCoreSynonyms()) {
            CustomDictionary.add(coreSynonym);
        }
        NLPTokenizer.ANALYZER.enableNumberQuantifierRecognize(true).enableCustomDictionaryForcing(true);
    }

    public void unloadCoreSynonyms(List<String> synonyms) {
        for (String synonym : synonyms) {
            if (CustomDictionary.get(synonym) == null) {
                CustomDictionary.add(synonym);
            }
        }
        for (String coreSynonym : getCoreSynonyms()) {
            CustomDictionary.add(coreSynonym);
        }
        NLPTokenizer.ANALYZER.enableNumberQuantifierRecognize(true).enableCustomDictionaryForcing(true);
    }

    public void loadCoreSynonyms(ExtractItem extractItem) {
        List<String> synonyms = Arrays.asList(extractItem.getSynonyms());
        for (String synonym : synonyms) {
            if (CustomDictionary.get(synonym) == null) {
                CustomDictionary.add(synonym);
            }
        }
        for (String coreSynonym : getCoreSynonyms()) {
            CustomDictionary.add(coreSynonym);
        }
        NLPTokenizer.ANALYZER.enableNumberQuantifierRecognize(true).enableCustomDictionaryForcing(true);
    }


    public void loadCoreSynonyms2(Map<String, ExtractBizModel> extractBizModelMap) {
        extractBizModelMap.forEach((k, v) -> {
            List<String> synonyms = v.getSynonyms();
            for (String synonym : synonyms) {
                if (CustomDictionary.get(synonym) == null) {
                    CustomDictionary.add(synonym);
                }
            }
        });
        for (String coreSynonym : getCoreSynonyms()) {
            CustomDictionary.add(coreSynonym);
        }
        NLPTokenizer.ANALYZER.enableNumberQuantifierRecognize(true).enableCustomDictionaryForcing(true);
    }

    public void unloadCoreSynonyms(ExtractItem extractItem) {
        List<String> synonyms = Arrays.asList(extractItem.getSynonyms());
        for (String synonym : synonyms) {
            if (CustomDictionary.contains(synonym)) {
                CustomDictionary.remove(synonym);
            }
        }
        NLPTokenizer.ANALYZER.enableNumberQuantifierRecognize(false).enableCustomDictionaryForcing(false);
    }

    public void unloadCoreSynonyms(ExtractBizModel extractBizModel) {
        List<String> synonyms = extractBizModel.getSynonyms();
        for (String synonym : synonyms) {
            if (CustomDictionary.contains(synonym)) {
                CustomDictionary.remove(synonym);
            }
        }
        NLPTokenizer.ANALYZER.enableNumberQuantifierRecognize(false).enableCustomDictionaryForcing(false);
    }

    public void unloadCoreSynonyms2(Map<String, ExtractBizModel> extractBizModelMap) {
        extractBizModelMap.forEach((k, v) -> {
            List<String> synonyms = v.getSynonyms();
            for (String synonym : synonyms) {
                if (CustomDictionary.contains(synonym)) {
                    CustomDictionary.remove(synonym);
                }
            }
        });
        NLPTokenizer.ANALYZER.enableNumberQuantifierRecognize(false).enableCustomDictionaryForcing(false);
    }


    private String[] getCoreSynonyms() {
        return new String[]{"近三年及一期", "近三年及一期末", "为", "及", "和"};
    }

    /**
     * 金额格式
     */
    protected boolean isZCFZ_JE(String text) {
        return regexUtil.isZCFZ_JE(text);
    }


    /**
     * 对外担保金额
     */
    protected boolean isDWDB_JE(String text) {
        return regexUtil.isDWDB_JE(text);
    }

    /**
     * 近三年及一期
     */
    protected boolean isJSNJYQ(String text) {
        return regexUtil.isJSNJYQ(text);
    }

    protected boolean isDSH(String text) {
        return regexUtil.isDSH(text);
    }


    protected boolean isHD_FDSBPJLYXSS(String text) {
        return regexUtil.isHD_FDSBPJLYXSS(text);
    }

    protected boolean isHD_FDSBPJLYXSS_UNIT(String text) {
        return regexUtil.isHD_FDSBPJLYXSS_UNIT(text);
    }

    protected boolean isDJG_UNIT(String text) {
        return regexUtil.isDJG_UNIT(text);
    }

    protected boolean isMT_SCCB(String text) {
        return regexUtil.isMT_SCCB(text);
    }

    protected boolean isMT_XSJG(String text) {
        return regexUtil.isMT_XSJG(text);
    }

    protected boolean isMT_SYKCCL(String text) {
        return regexUtil.isMT_SYKCCL(text);
    }

    protected boolean isMT_MTCL(String text) {
        return regexUtil.isMT_MTCL(text);
    }

    protected boolean isSX_YSYSX(String text) {
        return regexUtil.isSX_YSYSX(text);
    }

    protected boolean isSX_SXZE(String text) {
        return regexUtil.isSX_SXZE(text);
    }

    protected boolean isGT_CNLYL_UNIT(String text) {
        return regexUtil.isGT_CNLYL_UNIT(text);
    }

    protected boolean isGT_RJCGL_UNIT(String text) {
        return regexUtil.isGT_RJCGL_UNIT(text);
    }

    protected boolean isGT_CLGM_UNIT(String text) {
        return regexUtil.isGT_CLGM_UNIT(text);
    }


    protected boolean isGT_CNLYL(String text) {
        return regexUtil.isGT_CNLYL(text);
    }

    protected boolean isGT_RJCGL(String text) {
        return regexUtil.isGT_RJCGL(text);
    }

    protected boolean isGT_CLGM(String text) {
        return regexUtil.isGT_CLGM(text);
    }

    protected boolean isSN_SLCN(String text) {
        return regexUtil.isSN_SLCN(text);
    }

    protected boolean isSN_XKGMJ_UNIT(String text) {
        return regexUtil.isSN_XKGMJ(text);
    }

    protected boolean isSN_CNLYL_UNIT(String text) {
        return regexUtil.isSN_CNLYL(text);
    }

    protected boolean isSN_SLCN_UNIT(String text) {
        return regexUtil.isSN_SLCN(text);
    }

    protected boolean isSN_XKGMJ(String text) {
        return regexUtil.isSN_XKGMJ(text);
    }

    protected boolean isSN_CNLYL(String text) {
        return regexUtil.isSN_CNLYL(text);
    }

    protected boolean isGSGL_KYL(String text) {
        return regexUtil.isGSGL_KYL(text);
    }

    protected boolean isGSGL_HYL_UNIT(String text) {
        return regexUtil.isGSGL_HYL_UNIT(text);
    }

    protected boolean isGSGL_HYZZL_UNIT(String text) {
        return regexUtil.isGSGL_HYZZL_UNIT(text);
    }

    protected boolean isGSGL_KYL_UNIT(String text) {
        return regexUtil.isGSGL_KYL_UNIT(text);
    }

    protected boolean isGSGL_KYZZL_UNIT(String text) {
        return regexUtil.isGSGL_KYZZL_UNIT(text);
    }

    protected boolean isGSGL_KYZZL(String text) {
        return regexUtil.isGSGL_KYZZL(text);
    }

    protected boolean isGSGL_HYL(String text) {
        return regexUtil.isGSGL_HYL(text);
    }

    protected boolean isGSGL_HYZZL(String text) {
        return regexUtil.isGSGL_HYZZL(text);
    }

    protected String replaceAmtComma(String text) {
        return regexUtil.replaceAmtComma(text);
    }


    protected boolean isFDC_XSJE(String text) {
        return regexUtil.isFDC_XSJE(text);
    }

    protected boolean isFDC_TDCBGHZBMJ(String text) {
        return regexUtil.isFDC_TDCBGHJZMJ(text);
    }

    protected boolean isFDC_DSZBMJ(String text) {
        return regexUtil.isFDC_DSMJZB(text);
    }

    protected boolean isFDC_QYXSMJ(String text) {
        return regexUtil.isFDC_QYXSMJ(text);
    }

    protected boolean isFDC_XSJE_UNIT(String text) {
        return regexUtil.isFDC_XSJE_UNIT(text);
    }

    protected boolean isFDC_TDCBGHZBMJ_UNIT(String text) {
        return regexUtil.isFDC_TDCBGHJZMJ_UNIT(text);
    }

    protected boolean isFDC_DSZBMJ_UNIT(String text) {
        return regexUtil.isFDC_DSMJZB_UNIT(text);
    }

    protected boolean isFDC_QYXSMJ_UNIT(String text) {
        return regexUtil.isFDC_QYXSMJ_UNIT(text);
    }

    protected String joinSynonyms(String[] synonyms) {
        return regexUtil.joinSynonyms(synonyms);
    }

    protected String replaceFXJG_Prefix(String text) {
        return regexUtil.replaceFXJG_Prefix(text);
    }


    protected String replaceSpaces(String text) {
        return regexUtil.replaceSpaces(text);
    }

    protected String combineTextJsonArray(JsonArray jsonArray) {
        StringBuilder stringBuilder = new StringBuilder();
        JsonObject item = null;
        JsonObject previousItem = null;
        for (int i = 0; i < jsonArray.size(); i++) {
            item = jsonArray.get(i).getAsJsonObject();
            String text = item.get("text").getAsString().trim();
            if (StringUtils.isEmpty(text)) {
                continue;
            }
            if (i > 0) {
                previousItem = jsonArray.get(i - 1).getAsJsonObject();
                if (previousItem != null) {
                    double previousLeft = previousItem.get("left").getAsDouble();
                    if (previousLeft == 0) {
                        stringBuilder.append(text);
                    } else {
                        double itemLeft = item.get("left").getAsDouble();
                        if ((itemLeft - previousLeft) > 20) {
                            stringBuilder.append(" ");
                        }
                        stringBuilder.append(replaceSpaces(text));
                    }
                } else {
                    stringBuilder.append(text);
                }
            } else {
                stringBuilder.append(text);
            }
        }
        return stringBuilder.toString();
    }

    protected TextLayout findTextLayout(String text, List<PageModel> fragmentPageModelList) {
        PageModel pageModel = null;
        TextLayout vTextLayout = null;
        for (int i = 0; i < fragmentPageModelList.size(); i++) {
            pageModel = fragmentPageModelList.get(i);
            JsonElement pageData = pageModel.getJsonTextData();
            JsonArray dataArray = pageData.getAsJsonArray().get(0).getAsJsonObject().get("data").getAsJsonArray();
            for (int j = 0; j < dataArray.size(); j++) {
                JsonArray itemArray = dataArray.get(j).getAsJsonArray();
                String combineLine = combineTextJsonArray(itemArray);
                if (combineLine.contains(text)) {
                    vTextLayout = createKVTextLayout(pageModel, itemArray);
                    break;
                }
            }
            if (vTextLayout != null) {
                break;
            }
        }
        return vTextLayout;
    }

    protected TextLayout createKVTextLayout(PageModel pageModel, JsonObject jsonObject) {
        double top = jsonObject.get("top").getAsDouble();
        if (top == 0) {
            return null;
        }
        double left = jsonObject.get("left").getAsDouble();
        double height = jsonObject.get("height").getAsDouble();
        double width = jsonObject.get("width").getAsDouble();
        TextLayout textLayout = new TextLayout(replaceSpecialChar(jsonObject.get("text").getAsString()), pageModel.getPageNumber(), top, left, height, width);
        textLayout.setPageWidth(pageModel.getWidth());
        textLayout.setPageHeight(pageModel.getHeight());
        return textLayout;
    }

    protected JsonObject findValidTableCell(JsonArray itemArray) {
        List<JsonObject> jsonObjectList = findValidTableCells(itemArray);
        if (!jsonObjectList.isEmpty()) {
            return jsonObjectList.get(0);
        }
        return null;
    }


    protected TextLayout createKVTextLayout(PageModel pageModel, JsonArray jsonArray) {
        TextLayout textLayout = null;
        for (int i = 0; i < jsonArray.size(); i++) {
            JsonObject jsonObject = jsonArray.get(i).getAsJsonObject();
            textLayout = createKVTextLayout(pageModel, jsonObject);
            if (textLayout != null) {
                break;
            }
        }
        return textLayout;
    }
}
